www.gusucode.com > VC++ 实现带图标的ComboBox下拉列表框-源码程序 > VC++ 实现带图标的ComboBox下拉列表框-源码程序/code/IconComboBox.cpp

    //Download by http://www.NewXing.com



/////////////////////////////////  Includes  //////////////////////////////////
#include "stdafx.h"
#include "IconComboBox.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif


////////////////////////////// Locals /////////////////////////////////////////

struct _IconComboData
{
  HICON m_hIcon;
  UINT  m_nIconID;
};


////////////////////////////// Implementation /////////////////////////////////

void DDX_CBIcon(CDataExchange* pDX, int nIDC, UINT& nIconID)
{
	HWND hWndCtrl = pDX->PrepareCtrl(nIDC);
	CSmallIconComboBox* pCombo = (CSmallIconComboBox*) CWnd::FromHandle(hWndCtrl);
	ASSERT(pCombo);
	ASSERT(pCombo->IsKindOf(RUNTIME_CLASS(CSmallIconComboBox)));

	if (pDX->m_bSaveAndValidate)
    nIconID = pCombo->GetCurSelIcon();
	else
	  pCombo->SetCurSelIcon(nIconID);
}






IMPLEMENT_DYNAMIC(CSmallIconComboBox, CComboBox)

BEGIN_MESSAGE_MAP(CSmallIconComboBox, CComboBox)
	//{{AFX_MSG_MAP(CSmallIconComboBox)
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()

void CSmallIconComboBox::PreSubclassWindow() 
{
  //Let the parent do its thing
	CComboBox::PreSubclassWindow();

  //combo box must manage the strings
  ASSERT(GetWindowLong(m_hWnd, GWL_STYLE) & CBS_HASSTRINGS);

  //combo box must be owner draw variable
  ASSERT(GetWindowLong(m_hWnd, GWL_STYLE) & CBS_OWNERDRAWVARIABLE);

  //Set the Height of the combo box to just contain one small icon
  ::SendMessage(m_hWnd, CB_SETITEMHEIGHT, (WPARAM)-1, 18L);
}

int CSmallIconComboBox::AddIcon(UINT nIconID)
{
  //Load up the icon
  HICON hIcon = (HICON) LoadImage(AfxGetResourceHandle(), MAKEINTRESOURCE(nIconID), IMAGE_ICON, 16, 16, 0);
  ASSERT(hIcon != NULL);
  if (hIcon == NULL)
    return CB_ERR;

  //Add it to the combo box
  int nOffset = CComboBox::AddString(_T(""));

	//Hive away the info in the item data field
	_IconComboData* pData = new _IconComboData;
	pData->m_hIcon = hIcon;
	pData->m_nIconID = nIconID;
  SetItemData(nOffset, (DWORD) pData);

  //Return the offset at which it was added
	return nOffset;
}

int CSmallIconComboBox::InsertIcon(int nIndex, UINT nIconID)
{
  //Load up the icon
  HICON hIcon = (HICON) LoadImage(AfxGetResourceHandle(), MAKEINTRESOURCE(nIconID), IMAGE_ICON, 16, 16, 0);
  ASSERT(hIcon != NULL);
  if (hIcon == NULL)
    return CB_ERR;

  //Add it to the combo box at the specified offset
  int nOffset = CComboBox::InsertString(nIndex, _T(""));

	//Hive away the info in the item data field
	_IconComboData* pData = new _IconComboData;
	pData->m_hIcon = hIcon;
	pData->m_nIconID = nIconID;
  SetItemData(nOffset, (DWORD) pData);

  //Return the offset at which it was added
	return nOffset;
}

int CSmallIconComboBox::DeleteIcon(int nIndex)
{
  //just let the parent do its thing
  return CComboBox::DeleteString(nIndex);
}

UINT CSmallIconComboBox::GetCurSelIcon() const
{
  int nSel = GetCurSel();
	if (nSel == CB_ERR)
	  return 0;

	_IconComboData* pData = (_IconComboData*) GetItemData(nSel);
  return pData->m_nIconID;
}

int CSmallIconComboBox::SetCurSelIcon(UINT nIconID)
{
	//iterate through all the CB items and set the one which 
	//has the corresponding item data
	for (int i=0; i<GetCount(); i++)
	{
		_IconComboData* pData = (_IconComboData*) GetItemData(i);
		if (pData->m_nIconID == nIconID)
		  return SetCurSel(i);
	}
	TRACE(_T("Warning: Could not find matching icon in the icon combo box\n"));
	return CB_ERR;
}

void CSmallIconComboBox::MeasureItem(LPMEASUREITEMSTRUCT lpMeasureItemStruct) 
{
  lpMeasureItemStruct->itemHeight = 18;
}

void CSmallIconComboBox::DrawItem(LPDRAWITEMSTRUCT lpDIS) 
{
	ASSERT(lpDIS->CtlType == ODT_COMBOBOX);	

  //Create A CDC from the SDK struct passed in
	CDC* pDC = CDC::FromHandle(lpDIS->hDC);

  //If the item is selected, draw the selection background
	if ((lpDIS->itemState & ODS_SELECTED) &&                         
		(lpDIS->itemAction & (ODA_SELECT | ODA_DRAWENTIRE)))
	{
		// item has been selected - draw selection rectangle
		COLORREF crHilite = GetSysColor(COLOR_HIGHLIGHT);
		CBrush br(crHilite);
		pDC->FillRect(&lpDIS->rcItem, &br);
	}

  //If the item is not selected, draw a white background
	if (!(lpDIS->itemState & ODS_SELECTED) &&
		(lpDIS->itemAction & ODA_SELECT))
	{
		// Item has been de-selected -- remove selection rectangle
		CBrush br(RGB(255, 255, 255));
		pDC->FillRect(&lpDIS->rcItem, &br);
	}

  //Draw the icon
	_IconComboData* pData = (_IconComboData*) lpDIS->itemData;
	ASSERT(pData != NULL);
	if (pData && lpDIS->itemData != 0xFFFFFFFF)
    DrawIconEx(pDC->GetSafeHdc(), lpDIS->rcItem.left+1, lpDIS->rcItem.top+1, pData->m_hIcon, 16, 16, 0, NULL, DI_NORMAL);
}

void CSmallIconComboBox::DeleteItem(LPDELETEITEMSTRUCT lpDeleteItemStruct) 
{
  //Free up any existing HICON's used for drawing
	_IconComboData* pData = (_IconComboData*) GetItemData(lpDeleteItemStruct->itemID);
	ASSERT(pData);
	DestroyIcon(pData->m_hIcon);

	//Free up our internal structure which is stored in the item data
	delete pData;
	
	//Let the parent do its thing
	CComboBox::DeleteItem(lpDeleteItemStruct);
}

int CSmallIconComboBox::AddString(LPCTSTR /*lpszString*/)
{
	ASSERT(FALSE); //Use AddIcon not AddString
	return CB_ERR;
}

int CSmallIconComboBox::InsertString(int /*nIndex*/, LPCTSTR /*lpszString*/)
{
	ASSERT(FALSE); //Use InsertIcon not InsertString
	return CB_ERR;
}

int CSmallIconComboBox::DeleteString(int /*nIndex*/)
{
	ASSERT(FALSE); //Use DeleteIcon not DeleteString
	return CB_ERR;
}














IMPLEMENT_DYNAMIC(CLargeIconComboBox, CSmallIconComboBox)

BEGIN_MESSAGE_MAP(CLargeIconComboBox, CSmallIconComboBox)
	//{{AFX_MSG_MAP(CLargeIconComboBox)
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()

void CLargeIconComboBox::PreSubclassWindow() 
{
  //Let the parent do its thing
	CSmallIconComboBox::PreSubclassWindow();

  //Set the Height of the combo box to just contain one large icon
  ::SendMessage(m_hWnd, CB_SETITEMHEIGHT, (WPARAM)-1, 34L);
}

int CLargeIconComboBox::AddIcon(UINT nIconID)
{
  //Load up the icon
  HICON hIcon = (HICON) LoadImage(AfxGetResourceHandle(), MAKEINTRESOURCE(nIconID), IMAGE_ICON, 32, 32, 0);
  ASSERT(hIcon != NULL);
  if (hIcon == NULL)
    return CB_ERR;

  //Add it to the combo box
  int nOffset = CComboBox::AddString(_T(""));

	//Hive away the info in the item data field
	_IconComboData* pData = new _IconComboData;
	pData->m_hIcon = hIcon;
	pData->m_nIconID = nIconID;
  SetItemData(nOffset, (DWORD) pData);

  //Return the offset at which it was added
	return nOffset;
}

int CLargeIconComboBox::InsertIcon(int nIndex, UINT nIconID)
{
  //Load up the icon
  HICON hIcon = (HICON) LoadImage(AfxGetResourceHandle(), MAKEINTRESOURCE(nIconID), IMAGE_ICON, 32, 32, 0);
  ASSERT(hIcon != NULL);
  if (hIcon == NULL)
    return CB_ERR;

  //Add it to the combo box at the specified offset
  int nOffset = CComboBox::InsertString(nIndex, _T(""));

	//Hive away the info in the item data field
	_IconComboData* pData = new _IconComboData;
	pData->m_hIcon = hIcon;
	pData->m_nIconID = nIconID;
  SetItemData(nOffset, (DWORD) pData);

  //Return the offset at which it was added
	return nOffset;
}


void CLargeIconComboBox::MeasureItem(LPMEASUREITEMSTRUCT lpMeasureItemStruct) 
{
  lpMeasureItemStruct->itemHeight = 34;
}

void CLargeIconComboBox::DrawItem(LPDRAWITEMSTRUCT lpDIS) 
{
	ASSERT(lpDIS->CtlType == ODT_COMBOBOX);	

  //Create A CDC from the SDK struct passed in
	CDC* pDC = CDC::FromHandle(lpDIS->hDC);

  //If the item is selected, draw the selection background
	if ((lpDIS->itemState & ODS_SELECTED) &&                         
		(lpDIS->itemAction & (ODA_SELECT | ODA_DRAWENTIRE)))
	{
		// item has been selected - draw selection rectangle
		COLORREF crHilite = GetSysColor(COLOR_HIGHLIGHT);
		CBrush br(crHilite);
		pDC->FillRect(&lpDIS->rcItem, &br);
	}

  //If the item is not selected, draw a white background
	if (!(lpDIS->itemState & ODS_SELECTED) &&
		(lpDIS->itemAction & ODA_SELECT))
	{
		// Item has been de-selected -- remove selection rectangle
		CBrush br(RGB(255, 255, 255));
		pDC->FillRect(&lpDIS->rcItem, &br);
	}

  //Draw the icon
	_IconComboData* pData = (_IconComboData*) lpDIS->itemData;
	ASSERT(pData != NULL);
	if (pData && lpDIS->itemData != 0xFFFFFFFF)
    DrawIconEx(pDC->GetSafeHdc(), lpDIS->rcItem.left+1, lpDIS->rcItem.top+1, pData->m_hIcon, 32, 32, 0, NULL, DI_NORMAL);
}